# -*- coding: utf-8 -*-
# © 2016 Elico corp (www.elico-corp.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from datetime import date,datetime,timedelta,time as DT
from dateutil.relativedelta import relativedelta
import time
from pytz import timezone

from odoo import fields, models, api, tools,_
from odoo.exceptions import ValidationError
import pytz

from odoo.exceptions import UserError
import logging
_logger = logging.getLogger(__name__)


class HrContractCn(models.Model):
    _inherit = 'hr.contract'
    _sql_constraints = [
        ('children_education_amount_check',
         'CHECK(children_education_amount <= 1000)',
         "children education amount should not greater than 1000"),
        ('continuing_education_amount_check',
         'CHECK(continuing_education_amount <= 400)',
         "continuing education amount should not greater than 400"),
        ('medical_treatment_amount_check',
         'CHECK(medical_treatment_amount <= 5000)',
         "medical treatment amount should not greater than 5000"),
        ('housing_loans_interest_amount_check',
         'CHECK(housing_loans_interest_amount <= 1000)',
         "housing loans interests should not greater than 1000"),
        ('housing_rent_amount_check',
         'CHECK(housing_rent_amount <= 1200)',
         "housing rent amount should not greater than 1200"),
        ('elderly_support_amount_check',
         'CHECK(elderly_support_amount <= 2000)',
         "The value should not greater than 2000"),]

    social_insurance_amount = fields.Float(
        'Social Insurance Base',
        digits=(16,2)
    )
    housing_fund_base_amount = fields.Float(
        'Housing Fund Base',
        digits=(16,2),
        default=0
    )
    pit_base_amount = fields.Float(
        'PIT Base',
        digits=(16,2),
        default=0
    )
    pit_exemption_amount = fields.Float(
        'Individual Income Tax Threshold',
        digits=(16,2),
        required=True,
        default=5000.00
    )
    merit_salary_amount = fields.Float(
        'merit salary',
        digits=(16,2),
        default=0
    )

    children_education_amount = fields.Float(
        'Children education Fee',
        digits=(16,2)
    )
    continuing_education_amount = fields.Float(
        'Continuing education Fee',
        digits=(16,2),
        default=0
    )
    medical_treatment_amount = fields.Float(
        'Medical treatment Fee',
        digits=(16,2),
        default=0
    )
    housing_loans_interest_amount = fields.Float(
        'Interest on housing loans',
        digits=(16,2),
        required=True,
        default=0
    )
    housing_rent_amount = fields.Float(
        'Housing rent',
        digits=(16,2),
        default=0
    )

    elderly_support_amount = fields.Float(
        'Support for the elderly',
        digits=(16,2),
        default=0
    )

    
    
    @api.constrains('pit_base_amount')
    def _pit_base_amount_check(self):
        for rec in self:
            if not rec.pit_base_amount >= 5000:
                raise ValidationError(_('PIT Base must be greater than or equal to 5000.'))
            if not rec.pit_base_amount <= rec.wage:
                raise ValidationError(_('PIT Base must be less than or equal to wage.'))

class HrPayrollStructure(models.Model):
    _inherit = "hr.payroll.structure"

    name = fields.Char('Name', required=True, translate=True)


class HrSalaryRuleCategory(models.Model):
    _inherit = "hr.salary.rule.category"

    name = fields.Char('Name', required=True, translate=True)


class HrSalaryRule(models.Model):
    _inherit = "hr.salary.rule"
    _order = "sequence"

    name = fields.Char('Name', required=True, translate=True)


class HrPayslip(models.Model):
    _inherit = "hr.payslip"
    
    date_from = fields.Date(string='Date From', readonly=True, required=True,
        default=lambda self: fields.Date.to_string( (datetime.now() + relativedelta(months=-1, day=1)).date()), states={'draft': [('readonly', False)]})
    date_to = fields.Date(string='Date To', readonly=True, required=True,
        default=lambda self: fields.Date.to_string((datetime.now() + relativedelta(day=1, days=-1)).date()),
        states={'draft': [('readonly', False)]})

    
    
    def compute_sheet(self):

        return super(HrPayslip, self).compute_sheet()


    @api.model
    def get_worked_day_lines(self, contracts, date_from, date_to):
        """
        @param contract: Browse record of contracts
        @return: returns a list of dict containing the input that should be applied for the given contract between date_from and date_to
        """
        
        
        res = []
        # 仅当合同作为工作计划链接时填写
        for contract in contracts.sudo().filtered(lambda contract: contract.resource_calendar_id):
            #compute ovtime and attendance  
            #by guo
            contract.sudo().write({'early_go':0,'early_times':0,'late_come':0,'late_times':0,'ovt_weekday':0,'ovt_weekend':0,'ovt_legal':0})
            self.env['hr.attendance'].get_months_attend(date_from,date_to,contract.employee_id)
            self.env['hr.overtime'].get_months_overtime(date_from,date_to,contract.employee_id)
            ovtimes = []
            if contract.ovt_weekday >0:
                ovtimes.append({
                    'name':_('OVT Weekday'),
                    'sequence': 8,
                    'code': 'Weekday',
                    'number_of_days': round(contract.ovt_weekday*2/contract.work_hours)/2,
                    'number_of_hours': contract.ovt_weekday,
                    'contract_id': contract.id,
                })
            if contract.ovt_weekend >0:
                ovtimes.append({
                    'name':_('OVT Weekend'),
                    'sequence': 8,
                    'code': 'Weekend',
                    'number_of_days': round(contract.ovt_weekend*2/contract.work_hours)/2,
                    'number_of_hours': contract.ovt_weekend,
                    'contract_id': contract.id,
                })
            if contract.ovt_legal >0:
                ovtimes.append({
                    'name':_('OVT Legal'),
                    'sequence': 8,
                    'code': 'Legal',
                    'number_of_days': round(contract.ovt_legal*2/contract.work_hours)/2,
                    'number_of_hours': contract.ovt_legal,
                    'contract_id': contract.id,
                })

            day_from = datetime.combine(fields.Date.from_string(date_from), DT.min)
            day_to = datetime.combine(fields.Date.from_string(date_to), DT.max)

            # compute leave days
            leaves = {}
            calendar = contract.resource_calendar_id
            tz = timezone(calendar.tz)
            day_leave_intervals = contract.employee_id.list_leaves(day_from, day_to, calendar=contract.resource_calendar_id)
            for day, hours, leave in day_leave_intervals:
                holiday = leave.holiday_id
                current_leave_struct = leaves.setdefault(holiday.holiday_status_id, {
                    'name': holiday.holiday_status_id.name or _('Global Leaves'),
                    'sequence': 5,
                    'code': holiday.holiday_status_id.code or 'GLOBAL',
                    'number_of_days': 0.0,
                    'number_of_hours': 0.0,
                    'contract_id': contract.id,
                })
                current_leave_struct['number_of_hours'] += hours
                # current_leave_struct['number_of_hours'] += - hours
                work_hours = calendar.get_work_hours_count(
                    tz.localize(datetime.combine(day, DT.min)),
                    tz.localize(datetime.combine(day, DT.max)),
                    compute_leaves=False,
                )
                if work_hours:
                    current_leave_struct['number_of_days'] += hours / work_hours
                    # current_leave_struct['number_of_days'] += - hours / work_hours

            # compute worked days
            work_data = contract.employee_id._get_work_days_data(day_from, day_to, calendar=contract.resource_calendar_id)
            attendances = {
                'name': _("Normal Working Days paid at 100%"),
                'sequence': 1,
                'code': 'WORK100',
                'number_of_days': work_data['days'],
                'number_of_hours': work_data['hours'],
                'contract_id': contract.id,
            }

            res.append(attendances)
            res.extend(leaves.values())
            res.extend(ovtimes)
        return res
        
class HrPayslipLine(models.Model):
    _inherit = "hr.payslip.line"
    _order = "sequence"


class HrEmployee(models.Model):
    _inherit = "hr.employee"


    entry_date = fields.Date(string="Entry Date", default=lambda self: fields.Date.today())
    worked_years = fields.Integer(
        string='Worked Years',
        compute='_compute_worked_years'
    )

    
    @api.depends('entry_date')
    def _compute_worked_years(self):
        for rec in self:
            if rec.entry_date:
                rec.worked_years = (
                    datetime.now().date() - rec.entry_date
                ).days / 360
            else:
                rec.worked_years = 0


class HrLeaveType(models.Model):
    _inherit = "hr.leave.type"

    code = fields.Char('Leave Type Code', required=True, default="leave" ,help = "must be unique,do not have Blank space.")

class HrRuleInput(models.Model):
    _inherit = 'hr.rule.input'

    name = fields.Char(string='Description', required=True, translate = True)
